<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>类的基本知识</title>
</head>
<body>
    <script type="text/javascript">
        // 创建一个person类
        class Person{
            // 构造器方法
            constructor(name, age){
                // 构造器中的this是谁？- 类的实例对象
                this.name = name
                this.age = age
            }
            // 一般方法
            speak(){
                // speak方法放到了哪里？ - 类的原型对象上，供实例使用
                // 通过Person实例调用speak时，speak中的this就是Person实例
                console.log(`我叫${this.name}, 我的年龄是${this.age}`)
            }
        }
        // 创建一个Person的实例对象
        const p1 = new Person('tom', 18)
        console.log(p1)
        p1.speak()
        p1.speak.call({a:1,b:2})
        p1.speak.call({name:1,age:2})

        // 创建一个Student类，继承于Person类
        class Student extends Person{
            constructor(name, age, grade){
                super(name, age)
                this.grade = grade
                this.school = 'xxx'
            }
            // 重写从父类继承的方法
            speak(){
                console.log(`我叫${this.name}, 我的年龄是${this.age}, 我读的是${this.grade}年级`)
            }
            // study方法放到了哪里？ - 类的原型对象上，供实例使用
            // 通过Student实例调用study时，study中的this就是Student实例
            study(){
                console.log(`我很努力学习`)
            }
        }

        const s1 = new Student('小张', 15, '高一')
        console.log(s1);
        s1.speak()

    /*
      总结：
        1. 类中的构造器不是必须写的，要对实例进行一些初始化的操作，如添加指定属性时才写。
        2. 如果A类继承了B类，且A类中写了构造器，那么A类构造器中的super是必须要调用的。
        3. 类中所定义的方法，都是放到了类的原型对象上，供实例去使用
    */
    </script>
</body>
</html>